use core::ffi::c_void;

use crate::EfiStatus;

/// 从系统中申请内存页
pub type EfiAllocatePages = extern "efiapi" fn(
    ty: EfiAllocateType,
    memory_type: EfiMemoryType,
    pages: usize,
    memory: *mut EfiPhysicalAddress,
) -> EfiStatus;

/// 释放内存页
pub type EfiFreePages = extern "efiapi" fn(memory: EfiPhysicalAddress, pages: usize) -> EfiStatus;

/// 返回当前内存映射
pub type EfiGetMemoryMap = extern "efiapi" fn(
    memory_map_size: *mut usize,
    memory_map: *mut EfiMemoryDescriptor,
    map_key: *mut usize,
    descriptor_size: *mut usize,
    descriptor_version: *mut u32,
) -> EfiStatus;

/// 申请内存池
pub type EfiAllocatePool = extern "efiapi" fn(
    pool_type: EfiMemoryType,
    size: usize,
    buffer: *mut *mut c_void,
) -> EfiStatus;

/// 将内存池返回给系统
pub type EfiFreePool = extern "efiapi" fn(buffer: *mut c_void) -> EfiStatus;

pub struct EfiMemoryDescriptor {
    /// 内存区域的类型
    pub memory_type: u32,
    pub physical_start: EfiPhysicalAddress,
    pub virtual_start: EfiVirtualAddress,
    pub number_of_pages: u64,
    pub attribute: u64,
}
pub type EfiVirtualAddress = u64;

#[repr(C)]
pub enum EfiAllocateType {
    AllocateAnyPages,
    AllocateMaxAddress,
    AllocateAddress,
    MaxAllocateType,
}
pub enum EfiMemoryType {
    EfiReservedMemoryType,
    EfiLoaderCode,
    EfiLoaderData,
    EfiBootServicesCode,
    EfiBootServicesData,
    EfiRuntimeServicesCode,
    EfiRuntimeServicesData,
    EfiConventionalMemory,
    EfiUnusableMemory,
    EfiACPIReclaimMemory,
    EfiACPIMemoryNVS,
    EfiMemoryMappedIO,
    EfiMemoryMappedIOPortSpace,
    EfiPalCode,
    EfiPersistentMemory,
    EfiUnacceptedMemoryType,
    EfiMaxMemoryType,
}

pub type EfiPhysicalAddress = u64;
